#include "../includes/IPC.h"
#include <sys/socket.h>
#include <unistd.h>

// -------------------- 服务端工具类 ---------------------------------

IpcServer* IpcServer::instance_ = nullptr;

IpcServer& IpcServer::getInstance(const std::string& path){
    if(instance_ == nullptr){
        instance_ = new IpcServer(path);
    }
    return *instance_;
}

// 有参构造函数初始化服务端门户套接字
IpcServer::IpcServer(const std::string& path){
    fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if(fd == -1){
        std::cerr << "socket() failed: " << strerror(errno) << std::endl;
        return; // 或者抛出异常
    }

    // 尝试删除已存在的 socket 文件 (如果存在)
    unlink(path.c_str());
    struct sockaddr_un addr;
    memset(&addr, 0, sizeof addr);
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1);

    if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1){
        std::cerr << "bind() failed: " << strerror(errno) << std::endl;
        close(fd); // bind 失败时关闭 socket
        fd = -1; // 重置 fd
        return; 
    }

    if(listen(fd, 5) == -1){
        std::cerr << "listen() failed: " << strerror(errno) << std::endl;
        close(fd); // listen 失败时关闭 socket
        fd = -1;
        return;
    }
    std::cout << "IpcServer init success\n"; // 修正拼写
}

// 接受连接请求, 调用此函数会阻塞等待连接请求, 返回与客户端交互的套接字
int IpcServer::accept_conn(){
    return accept(fd, nullptr, nullptr);
}

// 接收来自客户端的消息
int IpcServer::receive_data(int client_fd, size_t expected_size, void* buf){
    return recv(client_fd, buf, expected_size, 0); // 使用recv()专门进行socket I/O
}

// 向客户端发送消息
int IpcServer::send_data(int client_fd, size_t size, const void* buf){
    return send(client_fd, buf, size, 0); // 使用send()专门进行socket I/O
}


// ---------------- 客户端工具类 --------------------

IpcClient* IpcClient::instance_ = nullptr;

IpcClient& IpcClient::getInstance(const std::string& path){
    if(instance_ == nullptr){
        instance_ = new IpcClient(path);
    }
    return *instance_;
}

// 有参构造函数初始化客户端套接字
IpcClient::IpcClient(const std::string& path){
    fd = socket(AF_UNIX, SOCK_STREAM, 0);
    socket_path = path;
}

// 向服务端发送连接请求
int IpcClient::conn_to_server(){
    if(fd == -1)return - 1;
    struct sockaddr_un addr;
    memset(&addr, 0, sizeof addr);
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path.c_str(), sizeof(addr.sun_path) - 1);
    return connect(fd, (struct sockaddr*)& addr, sizeof(addr));
}

// 接收来自服务端的消息
int IpcClient::receive_data(int client_fd, size_t expected_size, void* buf){
    return recv(client_fd, buf, expected_size, 0); // 使用recv()专门进行socket I/O
}

// 向服务端发送消息
int IpcClient::send_data(int client_fd, size_t size, const void* buf){
    return send(client_fd, buf, size, 0); // 使用send()专门进行socket I/O
}